package org.infodavid.common.persistence.impl;

import java.util.Properties;

import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool.Config;

import org.infodavid.common.annotations.AImplementation;
import org.infodavid.common.annotations.AImplementation.ERuntime;
import org.infodavid.common.persistence.IQueryParameter;
import org.infodavid.common.persistence.QueryParameterFactory;
import org.infodavid.common.pool.impl.ConfigLoaderHelper;

/**
 * The Class QueryParameterFactoryImpl.
 */
@AImplementation(value = QueryParameterFactory.class, runtime = ERuntime.DEFAULT)
final class QueryParameterFactoryImpl extends QueryParameterFactory {

  /**
   * The Class PoolableObjectFactoryImpl.
   */
  protected static final class PoolableObjectFactoryImpl extends BasePoolableObjectFactory {

    /**
     * non-Javadoc.
     * @return the object
     * @see org.apache.commons.pool.BasePoolableObjectFactory#makeObject()
     */
    @Override
    public Object makeObject() {
      return new QueryParameterImpl();
    }

    /**
     * non-Javadoc.
     * @param obj the obj
     * @throws Exception the exception
     * @see org.apache.commons.pool.BasePoolableObjectFactory#passivateObject(java.lang.Object)
     */
    @Override
    public void passivateObject(final Object obj) throws Exception {
      ((IQueryParameter)obj).init();

      super.passivateObject(obj);
    }
  }

  /** The Constant pool. */
  private final transient GenericObjectPool pool;

  /**
   * The Constructor.
   */
  protected QueryParameterFactoryImpl() {
    super();

    final Config config = new Config();
    final ConfigLoaderHelper helper = ConfigLoaderHelper.getInstance();
    final Properties properties = new Properties();
    final PoolableObjectFactory factory = new PoolableObjectFactoryImpl();

    helper.load(config, properties, factory);
    pool = helper.instantiate(factory, properties, config);
    pool.setConfig(config);
  }

  /**
   * Gets the delegate.
   * @return the delegate
   */
  public GenericObjectPool getDelegate() {
    return pool;
  }

  /*
   * (non-Javadoc)
   * @see org.infodavid.common.pool.AbstractPooledFactory#doBorrow()
   */
  @Override
  protected IQueryParameter doBorrow() {
    IQueryParameter obj = null;

    try {
      obj = (IQueryParameter)getDelegate().borrowObject();
    }
    catch (final Exception e) {
      throw new RuntimeException(e);
    }

    return obj;
  }

  /*
   * (non-Javadoc)
   * @see org.infodavid.common.pool.AbstractPooledFactory#doInvalidate(java.io.Serializable )
   */
  @Override
  protected void doInvalidate(final IQueryParameter obj) {
    try {
      getDelegate().invalidateObject(obj);
    }
    catch (final Exception e) {
      throw new RuntimeException(e);
    }
  }

  /*
   * (non-Javadoc)
   * @see org.infodavid.common.pool.AbstractPooledFactory#doRelease(java.io.Serializable )
   */
  @Override
  protected void doRelease(final IQueryParameter obj) {
    try {
      getDelegate().returnObject(obj);
    }
    catch (final Exception e) {
      throw new RuntimeException(e);
    }
  }
}
